﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using vudu.ClasesDominio;
using vudu.Datos.Fachada;
using vudu.Datos.SqlServer;

namespace vudu.Logica.Clases
{
    public class ControladorPractica
    {
        #region Atributos

            private Practica _practica;
            private EnlaceDatos _fachada;
            private Escuela _miEscuela;
            private List<HorarioDeClase> _listaHorarioProfesor;            
            private List<List<HorarioDeClase>> _listaHorarioSalon;

        #endregion
    
        #region Constructor

        public ControladorPractica()
        {
            _practica = new Practica();
            _fachada = new EnlaceDatos();
            _listaHorarioProfesor = new List<HorarioDeClase>();
            _listaHorarioSalon = new List<List<HorarioDeClase>>();

        }

        #endregion

        #region Gets y Sets

        public Practica practica
        {
            get { return _practica; }
            set { _practica = value; }
        }

        public List<HorarioDeClase> ListaHorarioProfesor
        {
            get { return _listaHorarioProfesor; }
            //set { _listaHorarioProfesor = value; }
        }
        public List<List<HorarioDeClase>> ListaHorarioSalon
        {
            get { return _listaHorarioSalon; }
            //set { _listaHorarioSalon = value; }
        }

        public EnlaceDatos fachadaDatos
        {
            get { return _fachada; }
        }

        #endregion

        #region Metodos de ControladorPractica

        #region Pases directos a capa de datos

        public List<Materia> ObtenerMateriasActivasConSeccTeoria(string nombreEscuela)
        {
            /* Esta funcion obtiene una lista de materias activadas del pensum vigente dado el nombre de la escuela */
            return fachadaDatos.ObtenerMateriasActivasConSeccTeoria(nombreEscuela);
        }

        public List<SeccionMateria> ArmarListaDeSeccionesDisponibles(int idEscuela, int idMateria)
        {
            /* Esta funcion retorna una lista de SeccionMateria dado el id de la escuela y el id de la materia a la
             * que pertenece */
            return fachadaDatos.ListaSeccionesMateria(idEscuela, idMateria);
        }
        
        public Escuela ArmarEscuela(string correoEscuela)
        {
            /* Esta funcion retorna una escuela llena dado el correo del rol */
            return fachadaDatos.ArmarEscuela(correoEscuela);
        }

        public List<Profesor> ConsultarProfesores(int idEscuela)
        {
            /* Esta funcion retorna una lista de los profesores que pertenecen a la escuela pasada por parametro */
            return fachadaDatos.ListaProfesores(idEscuela);
        }

        public List<Practica> ConsultarPracticasDadaSeccionMateria(int idSeccionMateria)
        {
            /* Esta funcion retorna la lista de practicas dado el id de la seccion teorica */
            return _fachada.ConsultarPracticasDadaSeccionMateria(idSeccionMateria);
        }

        public bool EliminarPractica(int idPractica)
        {
            /* Esta funcion se encarga de mandar a desactivar la practica cuyo id esta pasada por parametro */
            return new EnlaceDatos().EliminarPractica(idPractica);
        }

        public List<HorarioDeClase> ConsultarPractica(int idPractica)
        {
            /* Esta funcion se encarga de retornar la lista d elos horarios dado el id de la seccion practica */
            return new EnlaceDatos().ConsultarPractica(idPractica);
        }

        public bool ModificarPractica(Practica miPractica)
        {
            /* Esta funcion se encarga de modificar la Practica que es pasada por parametro */
            return _fachada.ModificarPractica(miPractica);
        }

        public List<Materia> ConsultarListaMateriasPractica(string nombreEscuela)
        {
            /* Esta funcion se encarga de retornar la lista de materia que poseen practicas */
            return _fachada.ConsultarListaMateriasPractica(nombreEscuela);
        }

        #endregion

        #region Funciones trabajadas

        public bool CrearPractica(Practica practica, int idSeccionMateria)
        {
            /* Esta funcion se encarga de realizar los distintos llamados de insercion a la base de datos que conforman
             * el agregar, entre estos estan la insercion en tablas de practica y de horarios */
            
            bool bandera = true;
            practica.IdPractica = fachadaDatos.UltimoIdPractica()+1;
            practica.statusPractica = "Activo";
            fachadaDatos.AgregarPractica(practica, idSeccionMateria);

            for (int i = 0; (i < practica.horarioDeClase.Count) && (bandera); i++)
            {
                if (!fachadaDatos.AgregarHorarioClase(practica.horarioDeClase[i], practica.IdPractica))
                { bandera = false; }
            }
            return bandera;
        }
        
        public List<Salon> SalonesDisponibles( HorarioDeClase horario, string nombreEscuela, int idEscuela, int idProfesor )
        {
            /* Esta funcion me retorna la lista de salones que estan disponibles en la escuela, para un horario y profesor determinado */

            List<Salon> retorno = new List<Salon>();

            ChoqueHorarioProfesorSalon(idEscuela, nombreEscuela, idProfesor);
            // RECORRO _listaHorarioSalon OCUPADOS POR SALON EN BUSCA DE LAS HORAS IGUALES
            for (int contador = 0; contador < _listaHorarioSalon.Count; contador++)
            {

                // SI LA BANDERA ES TRUE SE DETECTO UN CHOQUE
                bool bandera = false;
                List<HorarioDeClase> salon = new List<HorarioDeClase>();
                salon = _listaHorarioSalon[contador];

                // RECORRO SUBLISTA DE _listaHorarioSalon
                for ( int contador1 = 0; (contador1 < salon.Count) && ( !bandera ); contador1++ )
                {

                    // SI EL DIA ES EL MISMO ENTRO A COMPRAR HORARIOS
                    if (salon[contador1].Dia == horario.Dia)
                    {
                        //si
                        if((horario.HoraInicio.Hour != salon[contador1].HoraInicio.Hour) && 
                            (horario.HoraFin.Hour != salon[contador1].HoraFin.Hour))
                        {
                        // SI CHOCA EL HORARIO, CORTO EL FOR LEVANTANDO LA BANDERA
                            if (((horario.HoraInicio.Hour < salon[contador1].HoraInicio.Hour) &&
                                           (salon[contador1].HoraInicio.Hour < horario.HoraFin.Hour)) ||
                                           ((horario.HoraInicio.Hour < salon[contador1].HoraFin.Hour) &&
                                           (salon[contador1].HoraFin.Hour < horario.HoraFin.Hour)))
                            {
                                bandera = true;
                            }
                        }
                        else
                        { bandera = true; }
                    }

                }

                // SI BANDERA ES FALSA NO SE DETECTO CHOQUE, ESTE HORARIO ES CANDIDATO, AGREGO AL RETORNO
                if (!bandera)
                { 
                    Salon salonCandidato = new Salon();
                    salonCandidato = salon[contador].SalonDeClase;
                    retorno.Add(salonCandidato);
                }

            }
                return retorno;

        }

        public void ChoqueHorarioProfesorSalon(int idEscuela, string nombreEscuela, int idProfesor)
        {
            /* Esta funcion se encarga de globalizar los atributos de _listaHorarioProfesor y _listaHorarioSalon, ambas
             * listas significan: _listaHorarioProfesor, representa la lista de horarios que va a tener el profesor cuyo
             * id se recibio por parametro, con este horario seria posible determinar en que salon va a estar dicho profesor
             * y en que horario, cualquier hora del dia, en cualquier dia de la semana. _listaHorarioSalon: Representa
             * una lista de listas de horarios que se encuentran ordenados por salon, con esta lista determinamos en que horas
             * que estan ocupados los salones de toda la universidades */
            
            List<HorarioDeClase> listaHorarioProfesor = new List<HorarioDeClase>();
            List<Materia> listaMateria = new List<Materia>();
            List<SeccionMateria> listaSeccionMateria = new List<SeccionMateria>();

            //listaProfesor = _fachada.ListaProfesores(idEscuela);
            listaMateria = _fachada.ObtenerMateriasActivasConSeccTeoria(nombreEscuela);

            // RECORRO LA LISTA DE MATERIAS EN BUSCA DE SUS SECCIONESMATERIAS CON SUS PRACTICAS LLENAS
            for (int contador = 0; contador < listaMateria.Count(); contador++)
            {
                List<SeccionMateria> misSeccionMateria = new List<SeccionMateria>();
                misSeccionMateria = _fachada.ListaSeccionesMateria(idEscuela, listaMateria[contador].Codigo);
                // RECORRO LA LISTA DE SECIONESMATERIA DE LA MATERIA
                for (int contador1 = 0; contador1 < misSeccionMateria.Count(); contador1++)
                {
                    listaSeccionMateria.Add(misSeccionMateria[contador1]);
                    // COMPARO LAS CEDULAS DEL PROFESOR CON EL PROFESOR DE LA SECCIONMATERIA
                    if (misSeccionMateria[contador1].Profesor.Crn == idProfesor)
                    {

                        // RECORRO CADA HORARIO QUE POSEE misSeccionMateria PARA AGREGARLA A LA LISTA
                        for (int contador2 = 0; contador2 < misSeccionMateria[contador1].HorasClase.Count(); contador2++)
                        {
                            HorarioDeClase horarioClaseProf = new HorarioDeClase();
                            horarioClaseProf = misSeccionMateria[contador1].HorasClase[contador2];
                            listaHorarioProfesor.Add(horarioClaseProf);
                        }
                    }
                    //valido practica o no
                    if (misSeccionMateria[contador1].ListaPractica != null)
                    {
                        // RECORRO LA LISTA DE LAS PRACTICAS DE CADA SECCION MATERIA
                        for (int contador3 = 0; contador3 < misSeccionMateria[contador1].ListaPractica.Count(); contador3++)
                        {

                            // COMPRARO LA CEDULA DEL PROFESOR CON LA CEDULA DEL PROFESOR DE LA PRACTICA DE LA SECCIONMATERIA
                            if (misSeccionMateria[contador1].ListaPractica[contador3].profesor.Crn == idProfesor)
                            {

                                // RECORRO LA LISTA DE HORARIO DE LA PRACTICAS DE CADA SECCION MATERIA AGREGANDO A LA LISTAHORARIOPROFESOR
                                for (int contador4 = 0; contador4 < misSeccionMateria[contador1].ListaPractica[contador3].horarioDeClase.Count(); contador4++)
                                {
                                    HorarioDeClase horarioClaseProf = new HorarioDeClase();
                                    horarioClaseProf = misSeccionMateria[contador1].ListaPractica[contador3].horarioDeClase[contador4];
                                    listaHorarioProfesor.Add(horarioClaseProf);

                                }
                            }
                        }
                    }
                }
            }

            // GLOBALIZO LA LISTA DE HORARIOS DEL PROFESOR
            _listaHorarioProfesor = listaHorarioProfesor;

            // RECORRO LA LISTA DE SECIONESMATERIA DE LA MATERIA
            for (int contador = 0; contador < listaSeccionMateria.Count(); contador++)
            {

                SeccionMateria seccionActual = new SeccionMateria();
                seccionActual = listaSeccionMateria[contador];

                // RECORRO LA LISTA DE HORARIOS DE LA SECCION MATERIA
                for (int contador1 = 0; contador1 < seccionActual.HorasClase.Count(); contador1++)
                {

                    HorarioDeClase horarioActual = new HorarioDeClase();
                    horarioActual = seccionActual.HorasClase[contador1];

                    // VERIFICO SI EL horarioActual ESTA EN LA LISTA GLOBAL DE HORARIOS SALONES, SI NO ES ASI, AGREGO UNA LISTA NUEVA
                    if (!ExisteEnLista(horarioActual.SalonDeClase.NumeroSalon))
                    {

                        List<HorarioDeClase> horarioNuevo = new List<HorarioDeClase>();
                        horarioNuevo.Add(horarioActual);

                        _listaHorarioSalon.Add(horarioNuevo);

                    }

                    // SINO, ES PORQUE ESTA, RECORRO LA LISTA GLOBAL EN BUSCA DE LA POSICION DEL SALON  PARA AGREGARLA A SU LISTA
                    else
                    {

                        // RECORRO LISTA GLOBAL DE HORARIOS POR SALON
                        for (int contador2 = 0; contador2 < _listaHorarioSalon.Count(); contador2++)
                        {

                            List<HorarioDeClase> subListaHorario = new List<HorarioDeClase>();
                            subListaHorario = _listaHorarioSalon[contador2];

                            // PREGUNTO SI EL NOMBRE DEL SALON ES EL DE LA POSICION ACTUAL, SI ES ASI AGREGO A LA LISTA, SINO DEJO RECORRER
                            if (horarioActual.SalonDeClase.NumeroSalon == subListaHorario[0].SalonDeClase.NumeroSalon)
                            {

                                subListaHorario.Add(horarioActual);

                            }
                        }

                    }
                }

                //si tiene practicas
                if ((seccionActual.ListaPractica != null) && (seccionActual.ListaPractica.Count() > 0))
                {
                    // RECORRO LA LISTA DE PRACTICAS DE LA SECCION MATERIA ACTUAL
                    for (int index = 0; index < seccionActual.ListaPractica.Count(); index++)
                    {
                        Practica practicaActual = new Practica();
                        practicaActual = seccionActual.ListaPractica[index];

                        //RECORRO LOS HORARIOS DE LAS PRACTICAS
                        for (int contador1 = 0; contador1 < practicaActual.horarioDeClase.Count(); contador1++)
                        {
                            HorarioDeClase horarioActual = new HorarioDeClase();
                            horarioActual = practicaActual.horarioDeClase[contador1];

                            // VERIFICO SI EL horarioActual ESTA EN LA LISTA GLOBAL DE HORARIOS SALONES, SI NO ES ASI, AGREGO UNA LISTA NUEVA
                            if (!ExisteEnLista(horarioActual.SalonDeClase.NumeroSalon))
                            {

                                List<HorarioDeClase> horarioNuevo = new List<HorarioDeClase>();
                                horarioNuevo.Add(horarioActual);

                                _listaHorarioSalon.Add(horarioNuevo);

                            }

                            // SINO, ES PORQUE ESTA, RECORRO LA LISTA GLOBAL EN BUSCA DE LA POSICION DEL SALON  PARA AGREGARLA A SU LISTA
                            else
                            {

                                // RECORRO LISTA GLOBAL DE HORARIOS POR SALON
                                for (int contador2 = 0; contador2 < _listaHorarioSalon.Count(); contador2++)
                                {

                                    List<HorarioDeClase> subListaHorario = new List<HorarioDeClase>();
                                    subListaHorario = _listaHorarioSalon[contador2];

                                    // PREGUNTO SI EL NOMBRE DEL SALON ES EL DE LA POSICION ACTUAL, SI ES ASI AGREGO A LA LISTA, SINO DEJO RECORRER
                                    if (horarioActual.SalonDeClase.NumeroSalon == subListaHorario[0].SalonDeClase.NumeroSalon)
                                    {

                                        subListaHorario.Add(horarioActual);

                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private bool ExisteEnLista( int numeroSalon )
        {
            /* Esta funcion verifica la existencia de algun salon en la lista de listas de _listaHorarioSalon, retorna true
             * de ser encontrada */
            

            bool bandera = false;

            for (int contador = 0; contador < _listaHorarioSalon.Count(); contador++ )
            { 
                List<HorarioDeClase> subListaHorarios = new List<HorarioDeClase>();
                subListaHorarios = _listaHorarioSalon[contador];

                HorarioDeClase horarioActual = new HorarioDeClase();
                horarioActual = subListaHorarios[0];

                if ( horarioActual.SalonDeClase.NumeroSalon == numeroSalon )
                {
                    bandera = true;
                }
            
            }

            return bandera;
        }

        #endregion  

        #endregion

    }
}
